import pandas as pd
import numpy as np

data = {'A': ['x', 'y', 'z'], 'B': [1000, 2000, 3000], 'C': [10, 20, 30]}  # 字典、list
# 1、data：ndarray/字典/类似列表 | DataFrame数据；数据类型可以是ndarray、嵌套列表、字典等
# index：索引/类似列表 | 使用的索引；默认值为range(n)
print('1')
df = pd.DataFrame(data, index=['a', 'b', 'c'])
print(df)
print()

# 获取df数据
print('2')
print(df.values)
print()

# 获取df行索引
print('3')
print(df.index)
print()

# 获取df列索引（列标签）
print('4')
print(df.columns)
print()

# 创建的时候，如果指定了列标签，那么DataFrame的列也会按照指定的顺序进行排列
# columns：索引/类似列表 | 使用的列标签；默认值为range(n)
df = pd.DataFrame(data, columns=['C', 'B', 'A'], index=['a', 'b', 'c'])
print('5')
print(df)
print()

# 如果某列不存在，为其赋值，会创建一个新列。我们可以用这种方法来添加一个新的列
print('6')
df = pd.DataFrame(data, index=['a', 'b', 'c'])
df['D'] = 10
print(df)
print()

# 添加行的一种方法是先创建一个DataFrame，然后再使用append方法
print('7')
new_df = pd.DataFrame({'A': 'new', 'B': 4000, 'C': 40}, index=['d'])
df = df.append(new_df)
print(df)
print()

# 或者也可以使用loc方法来添加行
print('8')
df.loc['e'] = ['new2', 5000, 50, 10]
print(df)
print()

#####################################################################
print("########################################################################")

# 索引的存在，使得Pandas在处理缺漏信息的时候非常灵活
print('9')
df2 = pd.DataFrame([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'z'], columns=['E'])
print(df2)
print()

# 如果现在想要合并df和df2，使得df有一个新的列E，那么可以使用join方法
print('10')
print('join1')
print(df.join(df2))
print()

# df只接受索引已经存在的值。由于df2中没有索引e，所以是NaN值，而且df2索引为z的值已经丢失了。为了保留df2中索引为z的值，我们可以提供一个参数，告诉Pandas如何连接。
# how='outer'表示使用两个索引中所有值的并集。连接操作的其他选项还有inner（索引的交集）、left（默认值，调用方法的对象的索引值）、right（被连接对象的索引值）等。
print('11')
print('join2')
print(df.join(df2, how='outer'))

########################################################################
print("########################################################################")

# 在金融数据分析中，我们要分析的往往是时间序列数据。下面介绍一下如何基于时间序列生成DataFrame。
# 为了创建时间序列数据，我们需要一个时间索引。这里先生成一个DatetimeIndex对象的日期序列
# periods：整数/None | 如果start或者end空缺，就必须指定；从start开始，生成periods日期数据；默认为None
# freq：dtype | 周期；默认是D，即周期为一天。也可以写成类似5H的形式，即5小时。其他的频率参数见下文
print('12')
dates = pd.date_range('20160101', periods=8)
print(dates)
print()

# 接下来，我们再基于dates来创建DataFrame
print('13')
df3 = pd.DataFrame(np.random.randn(8, 4), index=dates, columns=list('ABCD'))
print(df3)
print()

#  按列求总和
print('14')
print(df3.sum())
print()

# 按列求均值
print('15')
print(df3.mean())
print()

# 按列求累计总和
print('16')
print(df3.cumsum())
print()

# 使用describe一键生成多种统计数据
print('17')
print(df3.describe())
print()

# 可以根据某一列的值进行排序
print('19')
print(df3.sort_values('A'))
print()

# 根据索引（日期）排序（这里是倒序）
print('20')
print(df3.sort_index(ascending=False))
print()

# 选取某一列，返回的是Series对象，可以使用df.A
print('22')
print(df3['A'])
print()

# 使用[]选取某几行
print('23')
print(df3[0:5])
print()

# 根据标签（Label）选取数据，使用的是loc方法
print('24')
print(df3.loc[dates[0]])
print()
print('25')
print(df3.loc[:, ['A', 'C']])
print()
print('26')
print(df3.loc['20160102':'20160106', ['A', 'C']])
print('2')
# 如果只有一个时间点，那么返回的值是Series对象
print('27')
print(df3.loc['20160102', ['A', 'C']])
print()

########################################################################
print("########################################################################")

# 上面介绍的是loc方法，是按标签（索引）来选取数据的。有时候，我们会希望按照DataFrame的绝对位置来获取数据，
# 比如，如果想要获取第3行第2列的数据，但不想按标签（索引）获取，那么这时候就可以使用iloc方法。
print('28')
print(df3.iloc[2])
print()
# 再来看一个示例
print('29')
print(df3.iloc[3:6, 1:3])
print()

########################################################################
print("########################################################################")
# 有时，我们需要选取满足一定条件的数据。这个时候可以使用条件表达式来选取数据。
# 这时传给df的既不是标签，也不是绝对位置，而是布尔数组（Boolean Array）
print('30')
print(df3.A > 0)
print()

# 上面操作生成了一个Series类型的布尔数组。可以通过这个数组来选取对应的行
# 从结果可以看到，A列中值大于0的所有行都被选择出来了，同时也包括了BCD列。
print('31')
print(df3[df3.A > 0])
print()

# 寻找df中所有大于0的数据，先生成一个全数组的布尔值
print('32')
print(df3 > 0)
print()

# 下面来看一下使用df>0选取出来的数据效果。有结果可以看到，大于0的数据都能显示，其他数据显示为NaN值。
print('33')
print(df3[df3 > 0])
print()

# 为df3添加新的一列E
print('34')
df3['E'] = 0
print(df3)
print()

# 使用loc改变一列值
print('35')
df3.loc[:, 'E'] = 1
print(df3)
print()

# 使用loc改变单个值
print('36')
df3.loc['2016-01-01', 'E'] = 2
print(df3)
print()

# 使用loc改变一列值
print('37')
df3.loc[:, 'D'] = np.array([2] * len(df3))
print(df3)
print()

# 使用loc的时候，x索引和y索引都必须是标签值。对于这个例子，使用日期索引明显不方便，需要输入较长的字符串，所以使用绝对位置会更好。
# 这里可以使用混合方法，DataFrame可以使用ix来进行混合索引。比如，行索引使用绝对位置，列索引使用标签
print('38')
# df3.ix[1,'E'] = 3
# df3.iloc[1,'E'] = 3  # 报错
print(df3)
print()
